home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / microcrn / issue_46.arc / ISR.ARC / CALL.C next >
Encoding:
C/C++ Source or Header  |  1988-05-11  |  3.3 KB  |  152 lines

  1. /*    CALL.c   routines to do far calls and software interrupts from 'C
  2.  
  3.         Supports ISR article in Micro Cornucopia Magazine Issue #46
  4. */
  5.  
  6.  
  7. #include <call.h>
  8.  
  9.  
  10. /*    SEG86
  11.  
  12.     This function simply copies the 8086 segment register contents
  13.     into the __regs register structure pointed at by ri.
  14. */
  15.  
  16. #pragma vpindex seg86
  17. unsigned int far seg86( ri )
  18. __regs far *ri;
  19. {
  20. #asm
  21.     push  es
  22.     push  es
  23.     les   bx, _RI
  24.     pop   ax
  25.     mov   _ES, ax
  26.     mov   _DS, ds
  27.     mov   _SS, ss
  28.     mov   _CS, cs
  29.     pushf
  30.     pop   ax
  31.     mov   _PSW, ax
  32.     pop   es
  33. #endasm
  34. }
  35.  
  36.  
  37. /*    CALL_8086()
  38.  
  39.     This function calls the code at _PC in *ri. It doesn't check
  40.     for messed up stacks, but is reentrant.
  41. */
  42.  
  43. #pragma vpindex call_8086
  44. unsigned int far call_8086( ri, ro )
  45. __regs far *ri, *ro;
  46. {
  47. #asm
  48.     push  si          ;save 'C regs
  49.     push  di
  50.     push  ds
  51.     push  es
  52.  
  53.     les   bx, _RI     ;get pointer to input regs
  54.  
  55.     push  bp          ;we're going to need this later...
  56.  
  57.     push  cs          ;here's where the routine that we'll call
  58.     mov   ax, offset retadr
  59.     push  ax          ;will return
  60.  
  61.     push  _CS         ;put address to call on the stack
  62.     push  _IP
  63.  
  64. do_it:    push  _ES         ;can't touch these now... 
  65.     push  _BX         ;  so put them on the stack
  66.  
  67.     mov   ax, _AX     ;load up the cpu regs
  68.     mov   cx, _CX
  69.     mov   dx, _DX 
  70.     mov   si, _SI
  71.     mov   di, _DI
  72.     mov   bp, _BP
  73.     mov   ds, _DS
  74.     pop   bx
  75.     pop   es
  76.  
  77.     ret               ;do the call
  78.  
  79. retadr:                      ;when the routine does a retf, we get here...
  80.     push  bp          ;save the current bp
  81.     mov   bp, sp      ;make it possible to get values off the stack
  82.     mov   bp, 2[bp]   ;get the value of BP that we had before the call
  83.  
  84.     push  es          ;save the current value of ES
  85.     push  bx          ;   and BX
  86.  
  87.     les   bx, _RO     ;get a pointer to the output register structure
  88.  
  89.     mov   _AX, ax     ;save the current value of AX
  90.     pop   ax          ;get the returned value of BX
  91.     mov   _BX, ax     ;  and save it too
  92.     pop   ax          ;get ES
  93.     mov   _ES, ax     ;save that...
  94.     mov   _CX, cx     ;and this...
  95.     mov   _DX, dx
  96.     mov   _DS, ds
  97.     mov   _SI, si
  98.     mov   _DI, di
  99.     pop   ax          ;then the BP that we last pushed
  100.     mov   _BP, ax
  101.     pop   ax          ;...get rid of the BP that we pushed before that
  102.     pushf             ;and last but not least, save the flags...
  103.     pop   ax
  104.     mov   _PSW, ax
  105.  
  106.     pop   es          ;restore 'C regs
  107.     pop   ds
  108.     pop   di
  109.     pop   si
  110. #endasm
  111. }
  112.  
  113.  
  114. /*    INTN_8086()
  115.  
  116.     This function calls the interrupt handler pointed at by
  117.     element (IP) in the 8086 interrupt vector table.
  118. */
  119.  
  120. #pragma vpindex intn_8086
  121. unsigned int far intn_8086( ri, ro )
  122. __regs far *ri, *ro;
  123. {
  124. #asm
  125.     push  si          ;save 'C regs
  126.     push  di
  127.     push  ds
  128.     push  es
  129.  
  130.     push  bp          ;we're going to need this later...
  131.  
  132.     les   bx, _RI     ;get pointer to input regs
  133.  
  134.     pushf             ;simulate an INT nn
  135.     push  cs          ;here's where the routine that we'll call
  136.     mov   ax, offset retadr
  137.     push  ax          ;will return
  138.  
  139.     mov   ax, _IP     ;interrupt number is hidden in _IP...
  140.     shl   ax, 1
  141.     shl   ax, 1
  142.     cwd
  143.     mov   es, dx
  144.     mov   bx, ax
  145.     push  es:word ptr 2[bx] ;put address to call on the stack
  146.     push  es:word ptr 0[bx]
  147.  
  148.     les   bx, _RI     ;restore the es:bx pointer to _RI
  149.     jmp   do_it       ;use the code in call_8086...
  150. #endasm
  151. }
  152.